package com.bkgy.controller.qualityDaily.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bkgy.controller.qualityDaily.entity.RepQuaMaterial;
import com.bkgy.controller.qualityDaily.entity.pdo.MaterialRepRes;
import com.bkgy.controller.qualityDaily.entity.pdo.QualityReq;
import com.bkgy.controller.qualityDaily.mapper.IQualitydailyMaterialRepMapper;
import com.bkgy.controller.qualityDaily.service.IQualitydailyMaterialRepService;
import com.bkgy.controller.tPdiDataL3Cgl1870.entity.TPdiDataL3Cgl1870;
import com.bkgy.controller.tPdiDataL3Cgl1870.service.ITPdiDataL3Cgl1870Service;
import com.bkgy.controller.tPdiDataL3Tcm2280.entity.TPdiDataL3Tcm2280;
import com.bkgy.controller.tPdiDataL3Tcm2280.service.ITPdiDataL3Tcm2280Service;
import com.bkgy.controller.technology.entity.TDefectData;
import com.bkgy.controller.technology.service.ITDefectDataService;
import com.bkgy.controller.tpdol3data.entity.TPdoDataL3Cgl1870;
import com.bkgy.controller.tpdol3data.entity.TPdoDataL3Tcm2280;
import com.bkgy.controller.tpdol3data.service.ITPdoL3Cal1630Service;
import com.bkgy.controller.tpdol3data.service.ITPdoL3Cal2150Service;
import com.bkgy.controller.tpdol3data.service.ITPdoL3Cgl1870Service;
import com.bkgy.controller.tpdol3data.service.ITPdoL3Tcm2280Service;
import com.bkgy.sys.common.constant.CommonConstant;
import com.bkgy.sys.common.entity.ResultData;
import com.bkgy.util.DateUtil;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

@Service
@RequiredArgsConstructor
public class QualitydailyMaterialRepServiceImpl extends ServiceImpl<IQualitydailyMaterialRepMapper, RepQuaMaterial>
        implements IQualitydailyMaterialRepService {
    private final ITDefectDataService defectService;
    private final ITPdiDataL3Tcm2280Service tcmPdiService;
    private final ITPdoL3Tcm2280Service tcmService;
    private final ITPdoL3Cal2150Service cal2150Service;
    private final ITPdoL3Cal1630Service cal1630Service;
    private final ITPdiDataL3Cgl1870Service cglPdiService;
    private final ITPdoL3Cgl1870Service cglService;
    private final IQualitydailyMaterialRepMapper mapper;

    @Override
    public ResultData<MaterialRepRes> materialRep(QualityReq req) {
        List<MaterialRepRes> list = new ArrayList<>();
        String[] unitArr = new String[]{"酸轧", "酸轧", "连退", "连退", "镀锌", "镀锌", "合计", "合计"};
        String[] typeArr = new String[]{"降级", "封闭返工", "降级", "封闭返工", "降级", "封闭返工", "降级", "封闭返工"};
        for (int i = 0; i < unitArr.length; i++) {
            MaterialRepRes res = new MaterialRepRes();
            res.setUnit(unitArr[i]);
            res.setType(typeArr[i]);
            list.add(res);
        }

        Date today = new Date();
        String beginTime = StringUtils.isNotEmpty(req.getDbegin()) ? req.getDbegin() : DateUtil.thisMonthFirstDay("yyyy-MM-dd");
        String endTime = StringUtils.isNotEmpty(req.getDend()) ? req.getDend() : DateUtil.nextMonthFirstDay("yyyy-MM-dd");

        //查询当日记录
        LambdaQueryWrapper<RepQuaMaterial> w1 = new LambdaQueryWrapper<>();
        w1.eq(RepQuaMaterial::getYearMonthDay, DateUtil.getDateToString(today, "yyyy-MM-dd"));
        RepQuaMaterial todayObj = getOne(w1);
        if (todayObj != null)
            pushObjToList(todayObj, list, false);

        //查询范围包括今天，把今天也累计到累计块
        Date d1 = DateUtil.getStringToDate("yyyy-MM-dd", beginTime);
        Date d2 = DateUtil.getStringToDate("yyyy-MM-dd", endTime);
        if (today.getTime() >= d1.getTime() && today.getTime() <= d2.getTime()) {
            pushObjToList(todayObj, list, true);
        }

        //查询历史记录
        RepQuaMaterial hisObj = mapper.selectSumHis(beginTime, endTime);
        pushObjToList(hisObj, list, true);

        //合计降级
        MaterialRepRes jiangjiObj = list.get(6);
        for (int i = 0; i < 5; i += 2) {
            MaterialRepRes materialRepRes = list.get(i);
            for (int m = 0; m < 4; m++) {
                try {
                    BigDecimal oldValue = (BigDecimal) jiangjiObj.getClass().getMethod("getDay" + m).invoke(jiangjiObj);
                    BigDecimal newValue = (BigDecimal) materialRepRes.getClass().getMethod("getDay" + m).invoke(materialRepRes);
                    jiangjiObj.getClass().getMethod("setDay" + m, BigDecimal.class).invoke(jiangjiObj, oldValue.add(newValue));
                    BigDecimal oldValue2 = (BigDecimal) jiangjiObj.getClass().getMethod("getSum" + m).invoke(jiangjiObj);
                    BigDecimal newValue2 = (BigDecimal) materialRepRes.getClass().getMethod("getSum" + m).invoke(materialRepRes);
                    jiangjiObj.getClass().getMethod("setSum" + m, BigDecimal.class).invoke(jiangjiObj, oldValue2.add(newValue2));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        //合计封闭
        list.get(7);
        for (int i = 1; i < 6; i += 2) {
            MaterialRepRes materialRepRes = list.get(i);
            for (int m = 0; m < 4; m++) {
                try {
                    BigDecimal oldValue = (BigDecimal) jiangjiObj.getClass().getMethod("getDay" + m).invoke(jiangjiObj);
                    BigDecimal newValue = (BigDecimal) materialRepRes.getClass().getMethod("getDay" + m).invoke(materialRepRes);
                    jiangjiObj.getClass().getMethod("setDay" + m, BigDecimal.class).invoke(jiangjiObj, oldValue.add(newValue));
                    BigDecimal oldValue2 = (BigDecimal) jiangjiObj.getClass().getMethod("getSum" + m).invoke(jiangjiObj);
                    BigDecimal newValue2 = (BigDecimal) materialRepRes.getClass().getMethod("getSum" + m).invoke(materialRepRes);
                    jiangjiObj.getClass().getMethod("setSum" + m, BigDecimal.class).invoke(jiangjiObj, oldValue2.add(newValue2));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return ResultData.ResultDataSuccess(list, list.size());
    }

    /**
     * 把材料对象压入列表对象
     *
     * @param dataObj 数据对象
     * @param list    返回前端的列表数据
     * @param isHis   是否压入累计区域
     */
    private void pushObjToList(RepQuaMaterial dataObj, List<MaterialRepRes> list, boolean isHis) {
        for (int i = 0; i < 6; i++) {
            MaterialRepRes row = list.get(i);
            for (int j = 0; j <= 3; j++) {
                try {
                    BigDecimal newValue = (BigDecimal) dataObj.getClass().getMethod("getCol" + i + j).invoke(dataObj);

                    BigDecimal oldValue = (BigDecimal) row.getClass().getMethod((isHis ? "getSum" : "getDay") + j).invoke(row);
                    row.getClass().getMethod((isHis ? "setSum" : "setDay") + j, BigDecimal.class).invoke(row, oldValue.add(newValue));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public boolean buildMaterialRepJob(Date date) {
        removeById(DateUtil.getDateToString(date, "yyyy-MM-dd"));

        RepQuaMaterial dayObj = new RepQuaMaterial();
        dayObj.setYearMonthDay(DateUtil.getDateToString(date, "yyyy-MM-dd"));

        //构建酸轧块数据
        buildTcm(dayObj, date);

        //TODO 连退块数据降级判断不明确
        buildCal(dayObj, date);

        //构建镀锌块数据
        buildCgl(dayObj, date);

        return save(dayObj);
    }

    /**
     * 构建镀锌块数据
     */
    private void buildCgl(RepQuaMaterial dayObj, Date date) {
        LambdaQueryWrapper<TPdoDataL3Cgl1870> w1 = new LambdaQueryWrapper<>();
        w1.ge(TPdoDataL3Cgl1870::getProdEndTime, DateUtil.getCurrentZero(date))
                .lt(TPdoDataL3Cgl1870::getProdEndTime, DateUtil.getNextDayZero(date));
        List<TPdoDataL3Cgl1870> pdoList = cglService.list(w1);
        Map<String, TPdoDataL3Cgl1870> map = new HashMap<>();
        List<String> entIdList = new ArrayList<>();
        for (TPdoDataL3Cgl1870 item : pdoList) {
            map.put(item.getExtid(), item);
            entIdList.add(item.getEntid());
        }

        //查询pdi表面等级标准
        Map<String, String> surfaceMap = new HashMap<>();
        LambdaQueryWrapper<TPdiDataL3Cgl1870> w2 = new LambdaQueryWrapper<>();
        w2.in(TPdiDataL3Cgl1870::getEntid, entIdList);
        List<TPdiDataL3Cgl1870> pdiList = cglPdiService.list(w2);
        for (TPdiDataL3Cgl1870 item : pdiList) {
            surfaceMap.put(item.getEntid(), item.getSurfaceCode());
        }

        BigDecimal banclgTotal = BigDecimal.ZERO;
        BigDecimal bancrzTotal = BigDecimal.ZERO;
        BigDecimal beiylgTotal = BigDecimal.ZERO;
        BigDecimal beiyrzTotal = BigDecimal.ZERO;
        BigDecimal banclgFbTotal = BigDecimal.ZERO;
        BigDecimal bancrzFbTotal = BigDecimal.ZERO;
        BigDecimal beiylgFbTotal = BigDecimal.ZERO;
        BigDecimal beiyrzFbTotal = BigDecimal.ZERO;

        //查询缺陷
        LambdaQueryWrapper<TDefectData> w3 = new LambdaQueryWrapper<>();
        w3.in(TDefectData::getExtId, map.keySet());
        List<TDefectData> defectList = defectService.list(w3);
        //分析缺陷》降级》归户
        for (TDefectData defect : defectList) {
            String extid = defect.getExtId();
            TPdoDataL3Cgl1870 pdo = map.get(extid);
            String surFaceCode = surfaceMap.get(pdo.getEntid());
            //镀锌降级判断，pdi表surfaceCode与pdo表的SurfaceAccuClassCode字段不一致
            if (!surFaceCode.equals(pdo.getSurfaceAccuClassCode())) {
                String guihu = CommonConstant.tPdi1870HomeMap.get(defect.getDefectAttributionCode1());
                if (guihu != null) {
                    String comm = defect.getDefectComment1();
                    if (guihu.contains("北营炼钢")) {
                        beiylgTotal = beiylgTotal.add(pdo.getOutMatWt());
                        if (comm.contains("封闭") && comm.indexOf("封闭") < 5)
                            beiylgFbTotal = beiylgFbTotal.add(pdo.getOutMatWt());
                    } else if (guihu.contains("钢坯:炼钢")) {
                        banclgTotal = banclgTotal.add(pdo.getOutMatWt());
                        if (comm.contains("封闭") && comm.indexOf("封闭") < 5)
                            banclgFbTotal = banclgFbTotal.add(pdo.getOutMatWt());
                    } else if (guihu.contains("板材热轧")) {
                        bancrzTotal = bancrzTotal.add(pdo.getOutMatWt());
                        if (comm.contains("封闭") && comm.indexOf("封闭") < 5)
                            bancrzFbTotal = bancrzFbTotal.add(pdo.getOutMatWt());
                    } else if (guihu.contains("北营轧钢")) {
                        beiyrzTotal = beiyrzTotal.add(pdo.getOutMatWt());
                        if (comm.contains("封闭") && comm.indexOf("封闭") < 5)
                            beiyrzFbTotal = beiyrzFbTotal.add(pdo.getOutMatWt());
                    }
                }
            }
        }

        dayObj.setCol40(banclgTotal);
        dayObj.setCol41(bancrzTotal);
        dayObj.setCol42(beiylgTotal);
        dayObj.setCol43(beiyrzTotal);
        dayObj.setCol50(banclgFbTotal);
        dayObj.setCol51(bancrzFbTotal);
        dayObj.setCol52(beiylgFbTotal);
        dayObj.setCol53(beiyrzFbTotal);
    }

    /**
     * 构建连退块数据
     */
    private void buildCal(RepQuaMaterial dayObj, Date date) {
        //TODO
        for (int i = 2; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                try {
                    dayObj.getClass().getMethod("setCol" + i + j, BigDecimal.class).invoke(dayObj, BigDecimal.ZERO);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 构建酸轧块数据
     */
    private void buildTcm(RepQuaMaterial dayObj, Date date) {
        LambdaQueryWrapper<TPdoDataL3Tcm2280> w1 = new LambdaQueryWrapper<>();
        w1.ge(TPdoDataL3Tcm2280::getProdEndTime, DateUtil.getCurrentZero(date))
                .lt(TPdoDataL3Tcm2280::getProdEndTime, DateUtil.getNextDayZero(date));
        List<TPdoDataL3Tcm2280> pdoList = tcmService.list(w1);
        Map<String, TPdoDataL3Tcm2280> map = new HashMap<>();
        List<String> entIdList = new ArrayList<>();
        for (TPdoDataL3Tcm2280 item : pdoList) {
            map.put(item.getExtid(), item);
            entIdList.add(item.getEntid());
        }

        //查询pdi表面等级标准
        Map<String, String> surfaceMap = new HashMap<>();
        LambdaQueryWrapper<TPdiDataL3Tcm2280> w2 = new LambdaQueryWrapper<>();
        w2.in(TPdiDataL3Tcm2280::getEntid, entIdList);
        List<TPdiDataL3Tcm2280> pdiList = tcmPdiService.list(w2);
        for (TPdiDataL3Tcm2280 item : pdiList) {
            surfaceMap.put(item.getEntid(), item.getCoatingType());
        }

        BigDecimal banclgTotal = BigDecimal.ZERO;
        BigDecimal bancrzTotal = BigDecimal.ZERO;
        BigDecimal beiylgTotal = BigDecimal.ZERO;
        BigDecimal beiyrzTotal = BigDecimal.ZERO;

        //查询缺陷
        LambdaQueryWrapper<TDefectData> w3 = new LambdaQueryWrapper<>();
        w3.in(TDefectData::getExtId, map.keySet());
        List<TDefectData> defectList = defectService.list(w3);
        //分析缺陷》降级》归户
        for (TDefectData defect : defectList) {
            String extid = defect.getExtId();
            TPdoDataL3Tcm2280 tcm = map.get(extid);
            String surFaceCode = surfaceMap.get(tcm.getEntid());
            //酸轧降级判断，不是0/00的记录缺陷表面等级与pdi表COATING_TYPE字段不一致
            if (!"0".equals(defect.getDefectClass1()) && !"00".equals(defect.getDefectClass1()) &&
                    !surFaceCode.equals(defect.getDefectClass1())) {
                String guihu = CommonConstant.tPdi1870HomeMap.get(defect.getDefectAttributionCode1());
                if (guihu != null) {
                    if (guihu.contains("北营炼钢")) {
                        beiylgTotal = beiylgTotal.add(tcm.getOutMatWt());
                    } else if (guihu.contains("钢坯:炼钢")) {
                        banclgTotal = banclgTotal.add(tcm.getOutMatWt());
                    } else if (guihu.contains("板材热轧")) {
                        bancrzTotal = bancrzTotal.add(tcm.getOutMatWt());
                    } else if (guihu.contains("北营轧钢")) {
                        beiyrzTotal = beiyrzTotal.add(tcm.getOutMatWt());
                    }
                }
            }
        }

        dayObj.setCol00(banclgTotal);
        dayObj.setCol01(bancrzTotal);
        dayObj.setCol02(beiylgTotal);
        dayObj.setCol03(beiyrzTotal);
        //酸轧不做封闭量
        dayObj.setCol10(BigDecimal.ZERO);
        dayObj.setCol11(BigDecimal.ZERO);
        dayObj.setCol12(BigDecimal.ZERO);
        dayObj.setCol13(BigDecimal.ZERO);
    }

    @Override
    public ResultData<JSONObject> materialPieRep(QualityReq req) {
        Date today = new Date();
        String beginTime = StringUtils.isNotEmpty(req.getDbegin()) ? req.getDbegin() : DateUtil.thisMonthFirstDay("yyyy-MM-dd");
        String endTime = StringUtils.isNotEmpty(req.getDend()) ? req.getDend() : DateUtil.nextMonthFirstDay("yyyy-MM-dd");

        JSONObject res = new JSONObject();
        String[] titleArr = new String[]{"板材炼钢", "板材热轧", "北营炼钢", "北营热轧"};
        //查询当日记录
        LambdaQueryWrapper<RepQuaMaterial> w1 = new LambdaQueryWrapper<>();
        w1.eq(RepQuaMaterial::getYearMonthDay, DateUtil.getDateToString(today, "yyyy-MM-dd"));
        RepQuaMaterial todayObj = getOne(w1);
        buildPie(todayObj, titleArr, res, "pie1");

        RepQuaMaterial hisObj = mapper.selectSumHis(beginTime, endTime);
        buildPie(hisObj, titleArr, res, "pie2");

        return ResultData.ResultDataSuccess(res);
    }

    private void buildPie(RepQuaMaterial todayObj, String[] titleArr, JSONObject res, String pieName) {
        if (todayObj != null) {
            BigDecimal total = BigDecimal.ZERO;
            for (int i = 0; i < 5; i += 2) {
                for (int j = 0; j < 4; j++) {
                    try {
                        BigDecimal v = (BigDecimal) todayObj.getClass().getMethod("getCol" + i + j).invoke(todayObj);
                        total = total.add(v);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            if (total.compareTo(BigDecimal.ZERO) > 0) {
                BigDecimal banclgSum = todayObj.getCol00().add(todayObj.getCol20()).add(todayObj.getCol40());
                BigDecimal banclgRate = banclgSum.multiply(BigDecimal.valueOf(100)).divide(total, 2, BigDecimal.ROUND_HALF_UP);
                JSONArray arr1 = new JSONArray();
                JSONObject obj1 = new JSONObject();
                obj1.put("name", titleArr[0]);
                obj1.put("value", banclgRate);
                arr1.add(obj1);
                BigDecimal bancrzSum = todayObj.getCol01().add(todayObj.getCol21()).add(todayObj.getCol41());
                BigDecimal bancrzRate = bancrzSum.multiply(BigDecimal.valueOf(100)).divide(total, 2, BigDecimal.ROUND_HALF_UP);
                JSONObject obj2 = new JSONObject();
                obj2.put("name", titleArr[1]);
                obj2.put("value", bancrzRate);
                arr1.add(obj2);
                JSONObject obj3 = new JSONObject();
                BigDecimal beiylgSum = todayObj.getCol02().add(todayObj.getCol22()).add(todayObj.getCol42());
                BigDecimal beiylgRate = beiylgSum.multiply(BigDecimal.valueOf(100)).divide(total, 2, BigDecimal.ROUND_HALF_UP);
                obj3.put("name", titleArr[2]);
                obj3.put("value", beiylgRate);
                arr1.add(obj3);
                JSONObject obj4 = new JSONObject();
                BigDecimal beiyrzSum = todayObj.getCol03().add(todayObj.getCol23()).add(todayObj.getCol43());
                BigDecimal beiyrzrzRate = beiyrzSum.multiply(BigDecimal.valueOf(100)).divide(total, 2, BigDecimal.ROUND_HALF_UP);
                obj4.put("name", titleArr[3]);
                obj4.put("value", beiyrzrzRate);
                arr1.add(obj4);

                res.put(pieName, arr1);
            } else {
                res.put(pieName, buildZeroPie(titleArr));
            }
        } else res.put(pieName, buildZeroPie(titleArr));
    }

    private JSONArray buildZeroPie(String[] titleArr) {
        JSONArray arr = new JSONArray();
        for (int i = 0; i < titleArr.length; i++) {
            JSONObject obj = new JSONObject();
            obj.put("name", titleArr[i]);
            obj.put("value", 0);
            arr.add(obj);
        }
        return arr;
    }
}
